package com.gitee.swaggeradmin.doc;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
 * 解析swagger3的json内容，v3的json内容大部分跟v2版本一样，有些地方稍微有点区别
 * 方法重写部分表示跟v2不一样的地方
 *
 * @author tanghc
 */
public class Swagger3DocParser extends SwaggerDocParser {

    @Override
    protected String getRequestUrl(JSONObject docRoot) {
        // {
        //            "url": "http://localhost:8808",
        //            "description": "Inferred Url"
        //        }
        JSONObject server = docRoot.getJSONArray("servers").getJSONObject(0);
        return server.getString("url");
    }

    /**
     * <pre>
     * "requestBody": {
     *                     "content": {
     *                         "application/json": {
     *                             "schema": {
     *                                 "$ref": "#/components/schemas/用户基本信息"
     *                             }
     *                         }
     *                     }
     *                 }
     * </pre>
     * @param docInfo
     * @return
     */
    @Override
    protected List<String> getConsumes(JSONObject docInfo) {
        Set<String> consumes = Optional.ofNullable(docInfo.getJSONObject("requestBody"))
                .flatMap(jsonObject -> Optional.ofNullable(jsonObject.getJSONObject("content")))
                .map(JSONObject::keySet)
                .orElse(Collections.emptySet());
        return new ArrayList<>(consumes);
    }

    @Override
    protected List<String> getProduces(JSONObject docInfo) {
        Set<String> consumes = Optional.ofNullable(docInfo.getJSONObject("responses"))
                .flatMap(jsonObject -> Optional.ofNullable(jsonObject.getJSONObject("200")))
                .flatMap(jsonObject -> Optional.ofNullable(jsonObject.getJSONObject("content")))
                .map(JSONObject::keySet)
                .orElse(Collections.emptySet());
        return new ArrayList<>(consumes);
    }

    @Override
    protected JSONObject getDefinitions(JSONObject docRoot) {
        return docRoot.getJSONObject("components").getJSONObject("schemas");
    }

    @Override
    protected JSONArray getEnum(JSONObject fieldJson) {
        return Optional.ofNullable(fieldJson.getJSONObject("schema"))
                .flatMap(schema -> Optional.ofNullable(schema.getJSONArray("enum")))
                .orElse(null);
    }

    @Override
    protected RefInfo getResponseRefInfo(JSONObject docInfo) {
        return Optional.ofNullable(docInfo.getJSONObject("responses"))
                .flatMap(jsonObject -> Optional.ofNullable(jsonObject.getJSONObject("200")))
                .flatMap(jsonObject -> Optional.ofNullable(jsonObject.getJSONObject("content")))
                .flatMap(jsonObject -> {
                    String mediaType = jsonObject.keySet().iterator().next();
                    JSONObject schema = jsonObject
                            .getJSONObject(mediaType)
                            .getJSONObject("schema");
                    return Optional.ofNullable(schema);
                })
                .map(this::getRefInfo)
                .orElse(null);
    }

    /*
    "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/用户基本信息"
                            }
                        }
                    }
                }
     */
    @Override
    protected JSONArray getParameterObject(JSONObject docInfo) {
        JSONArray jsonArray = super.getParameterObject(docInfo);
        if (jsonArray.isEmpty()) {
            JSONObject requestBody = docInfo.getJSONObject("requestBody");
            Optional.ofNullable(requestBody)
                    .flatMap(jsonObject -> Optional.ofNullable(jsonObject.getJSONObject("content")))
                    .flatMap(jsonObject -> {
                        String mediaType = jsonObject.keySet().iterator().next();
                        JSONObject schema = jsonObject
                                .getJSONObject(mediaType);
                        return Optional.ofNullable(schema);
                    })
                    .ifPresent(jsonArray::add);
        }
        return jsonArray;
    }

    /*
        {
                            "name": "pageIndex",
                            "in": "query",
                            "description": "查看第几页",
                            "required": true,
                            "style": "form",
                            "schema": {
                                "type": "integer",
                                "format": "int32"
                            }
                        }
         */
    @Override
    protected String getFieldType(JSONObject fieldJson) {
        JSONObject schema = fieldJson.getJSONObject("schema");
        if (schema == null) {
            return "string";
        }
        return schema.getString("type");
    }
}
